import 'dart:io';
import 'dart:isolate';

import 'package:equatable/equatable.dart';
import 'package:excel_utils/pages/month_report/isloate/month_isloate_extract_merge.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

part 'month_data_merging_event.dart';
part 'month_data_merging_state.dart';

class MonthDataMergingBloc extends Bloc<MonthDataMergingEvent, MonthDataMergingState> {
  MonthDataMergingBloc() : super(MonthDataMergingInitial()) {
    on<MonthDataMergingEvent>((event, emit) {});
    on<MonthSelectChildFileEvent>((event, emit) async {
      List<File> newChildFiles = List.from(event.childFiles);
      var filePickerResult = await FilePicker.platform.pickFiles(allowedExtensions: ['xlsx'], type: FileType.custom, allowMultiple: true);
      if (filePickerResult != null) {
        final Set<String> addedFilePaths = newChildFiles.map((file) => file.path).toSet();
        for (var value in filePickerResult.files) {
          var filePath = value.path.toString();
          if (!addedFilePaths.contains(filePath)) {
            newChildFiles.add(File(filePath));
            addedFilePaths.add(filePath);
          }
        }
        emit(MonthDataMergingSelectChildDataState(childFiles: newChildFiles));
      }
    });
    on<MonthClearChildFileEvent>((event, emit) async {
      emit(MonthDataMergingChildFilesClearState());
    });
    on<MonthOpenChildFileEvent>((event, emit) async {
      File file = event.file;
      if (Platform.isWindows) {
        Process.run('explorer.exe', ['/select,', file.path]);
      }
      emit(MonthDataMergingOpenFileState(file: File(file.path)));
    });
    on<MonthRemoveChildFileEvent>((event, emit) async {
      emit(MonthDataMergingRemoveChildFileState(index: event.index, childFile: event.file));
    });
    on<MonthExtractChildFileEvent>((event, emit) async {
      try {
        StringBuffer analysisRes = StringBuffer();
        analysisRes.clear();
        emit(MonthExtractChildFileLoadingState());
        ReceivePort receivePort = ReceivePort();
        List<File> childFiles = event.childFiles;
        String sheetName = event.sheetName;
        List<List<dynamic>> originData = [];
        final args = {"data": childFiles, "sheetName": sheetName, "sendPort": receivePort.sendPort};
        await Isolate.spawn(extractData, args);
        await for (var data in receivePort) {
          int code = data["code"];
          if (code == 0) {
            receivePort.close();
            originData.clear();
            originData.addAll(data["data"]);
            emit(MonthExtractChildFileSuccessState(originDataTemp: originData));
            break;
          } else if (code == 3) {
            emit(MonthExtractChildFileProcessState(msg: data["msg"]));
          } else {
            emit(MonthExtractChildFileFailureState(msg: data["msg"]));
          }
        }
      } catch (e) {
        emit(MonthExtractChildFileFailureState(msg: '解析子文件失败，请检查文件格式'));
      }
    });

    on<MonthSelectMainFileEvent>((event, emit) async {
      var filePickerResult = await FilePicker.platform.pickFiles(
        allowedExtensions: ['xlsx'],
        type: FileType.custom,
        allowMultiple: true,
      );
      if (filePickerResult != null) {
        File mainFile = File(filePickerResult.files.single.path.toString());
        emit(MonthDataMergingSelectMainDataState(mainFile: mainFile));
      }
    });
    on<MonthMainFileResetEvent>((event, emit) async {
      emit(MonthDataMergingResetMainDataState());
    });

    on<MonthMergingXlsxDataLoadingEvent>((event, emit) async {
      try {
        File? mainFile = event.mainFile;
        List<List<dynamic>> originData = event.originData;
        String mainSheetName = event.mainSheetName;
        bool isMergeLoading = event.isMergeLoading;
        if (isMergeLoading) {
          emit(const MonthExtractMainFileFailureState(msg: "正在合并，请勿重复操作"));
          emit(MonthDataMergingInitial());
          return;
        }
        if (mainFile == null) {
          String msg = "请选择需要合并的文件,主文件";
          emit(MonthExtractMainFileFailureState(msg: msg.toString()));
          emit(MonthDataMergingInitial());
          return;
        }
        if (originData.isEmpty) {
          emit(const MonthExtractMainFileFailureState(msg: "暂无有需要合并的数据，是否未提取数据？"));
          emit(MonthDataMergingInitial());
          return;
        }
        emit(const MonthMergingXlsxDataProgressState(resultMsg: '正在合并...', margeProgress: 0.0));
        ReceivePort receivePort = ReceivePort();
        final args = {"sendPort": receivePort.sendPort, "mainFile": mainFile, "originData": originData, "sheetName": mainSheetName, "isNullHeader": false};
        await Isolate.spawn(mergeData, args);
        await for (var data in receivePort) {
          int code = data["code"];
          if (code == 0) {
            emit(MonthExtractMainFileSuccessState(msg: data["msg"]));
            receivePort.close();
            break;
          } else if (code == 1) {
            emit(MonthExtractMainFileFailureState(msg: data["msg"]));
          } else if (code == 2) {
            emit(MonthMergingXlsxDataProgressState(resultMsg: data["msg"], margeProgress: data["value"] ?? 0.0));
          }
        }
      } catch (e) {
        emit(MonthExtractMainFileFailureState(msg: "合并异常"));
      }
    });
  }
}
